package com.hillky.watcher;

import com.hillky.NettyBootstrapInitializer;
import com.hillky.YrpcBootstrap;
import com.hillky.discovery.Registry;
import com.hillky.loadbalancer.LoadBalancer;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;

import java.net.InetSocketAddress;
import java.util.List;
import java.util.Map;

@Slf4j
public class UpAndDownWatcher implements Watcher {
    @Override
    public void process(WatchedEvent event) {

        if(event.getType()==Event.EventType.NodeChildrenChanged){
            if(log.isDebugEnabled()){
                log.debug("检测到服务[{}]有节点上/下线，将重新拉取服务列表",event.getPath());
            }

            String serviceName= getServiceName(event.getPath());

            // 重新拉取服务列表
            Registry registry = YrpcBootstrap.getInstance().getConfiguration().getRegistryConfig().getRegistry();
            List<InetSocketAddress> addresses = registry.lookup(serviceName,YrpcBootstrap.getInstance().getConfiguration().getGroup());

            // 处理新增节点
            for (InetSocketAddress address : addresses) {
                // 新增的节点会在address 不在cache中
                // 新增的节点不会在address 可能在cache中
                if(!YrpcBootstrap.CHANNEL_CACHE.containsKey(address)){
                    //根据地址建立连接，并且缓存
                    Channel channel=null;
                    try {
                        channel= NettyBootstrapInitializer.getBootstrap().connect(address).sync().channel();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    YrpcBootstrap.CHANNEL_CACHE.put(address,channel);
                }
            }

            // 处理下线的节点
            for (Map.Entry<InetSocketAddress, Channel> entry : YrpcBootstrap.CHANNEL_CACHE.entrySet()) {
                if(!addresses.contains(entry.getKey())){
                    YrpcBootstrap.CHANNEL_CACHE.remove(entry.getKey());
                }
            }

            // 需要获得负载均衡器,进行重新的loadBalance
            LoadBalancer loadBalancer = YrpcBootstrap.getInstance().getConfiguration().getLoadBalancer();
            loadBalancer.reLoadBalance(serviceName,addresses);

        }
    }

    private String getServiceName(String path) {
        String[] split = path.split("/");
        return split[split.length-1];
    }
}
